package com.yuelife.market.service.impl;

import com.yuelife.market.dao.MOrderDao;
import com.yuelife.market.dao.MProductDao;
import com.yuelife.market.entity.MOrder;
import com.yuelife.market.entity.MProduct;
import com.yuelife.market.service.MOrderService;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * (MOrder)表服务实现类
 *
 * @author makejava
 * @since 2020-06-11 23:04:04
 */
@Service
public class MOrderServiceImpl implements MOrderService {
    @Autowired
    private MOrderDao mOrderDao;
    @Autowired
    private MProductDao mProductDao;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public MOrder queryById(Integer id) {
        return this.mOrderDao.queryById(id);
    }

    /**
     * 查询多条数据
     *
     * @param offset 查询起始位置
     * @param limit 查询条数
     * @return 对象列表
     */
    @Override
    public List<MOrder> queryAllByLimit(int offset, int limit) {
        return this.mOrderDao.queryAllByLimit(offset, limit);
    }

    /**
     * 新增数据
     * @param mOrder 实例对象
     * @return 实例对象
     * 创建订单，默认是未支付的，需要买家自己点击支付才可以，如果30分钟之后订单还是未支付，那么订单失效，变为无效订单
     * 在新增订单之前，需要将对应的商品状态修改为已购买状态，但是订单失效后，该商品需要回复到无人购买的状态
     * 但是在最开始之前还需要判断该商品是否已经被别人购买了，因为会存在多人购买一件商品的时候，商品只有有一个，所以不能创建多个订单
     * 执行了两个SQL  加个事务注解 @Transactional
     */
    @Transactional
    @Override
    public Map insert(MOrder mOrder) {
        Map map=new HashMap();
        //得到商品编号
        String productSn=mOrder.getProductSn();
        //开始之前查看订单中是否有这个商品，如果有，那么创建订单失败，商品告罄
//        MOrder order=mOrderDao.selectOrderByProductSn(productSn);
        MProduct mProduct=mProductDao.selectProductBySn(productSn);   //这里有点bug，当数据库有两条商品时  一个失效一个未支付，然后又去创建  会报错  什么什么one many
        if (mProduct.getStatus()==1){
            //order.getOrderStatus().equals("0")||order.getOrderStatus().equals("1")
//            System.out.println("有订单了");
            map.put("code",300);
            return map;
        }else {
            //如果订单表中没有该商品信息，那么创建订单
            //商品状态，修改为商品已购买
            int status=1;
            //获取当前回复时间
            Date date=new Date();
            //时间格式
            SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String da=timeFormat.format(date);
            //生成UUID
            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
            //创建订单时间
            mOrder.setCreateOrderTime(da);
            //创建订单号，利用UUID
            mOrder.setOrderSn(uuid);
            //创建订单之前，修改商品状态
            Long i=mProductDao.updateStatusByProductSn(productSn,status);//修改商品状态
            if (i!=null&&i>0){
                //并且修改redis中的商品列表数据
                redisTemplate.opsForHash().delete("myProductList",productSn);
                System.out.println("创建订单时，订单信息先进行存储在交换机中");
                //我们这里用到rabbitmq的原因，是由于：所以的商品列表在redis中，而redis的处理速度高于mysql，如果存在高并发的情况，接下↓↓↓↓
                //高并发：那么就在一瞬间有很多order需要处理，那么会对mysql数据库大量的操作，会形成阻塞，而使用消息队列的时候，直接将需要处理的订单，接下↓↓↓↓
                //将订单存入到消息队列中，消息队列再限流被消费，消费的时候将消息数据存入到数据库
                //将数据存入交换机中  参数一：消息到达哪个交换机，参数二：路由key，以后消费者需要什么消息，直接用路由key限制， 参数三：消息数据
                rabbitTemplate.convertAndSend("order-exchange","order."+mOrder.getOrderSn(),mOrder);
                map.put("code",200);
                map.put("uuid",uuid);
                return map;
            }else {
                map.put("code",500);
                return map;
            }
        }
    }

    /**
     * 修改数据
     *
     * @param mOrder 实例对象
     * @return 实例对象
     */
    @Override
    public void update(MOrder mOrder) {
        this.mOrderDao.update(mOrder);
        System.out.println(mOrder.getId());
        System.out.println("我是业务层");
        System.out.println(mOrder.getOrderStatus());
//        return this.queryById(mOrder.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer id) {
        return this.mOrderDao.deleteById(id) > 0;
    }

    /**
     * 根据商品编号查询得到订单信息
     * @param orderSn
     * @return
     */
    @Override
    public MOrder orderInfoByOrderSn(String orderSn) {
        return mOrderDao.selectOrderByorderSn(orderSn);
    }

    /**
     * 查询订单
     * @param mOrder
     * @return
     */
    @Override
    public List<MOrder> selectOrder(MOrder mOrder) {
        return mOrderDao.queryAll(mOrder);
    }

    @Override
    public void updateBySn(MOrder mOrder) {
        mOrderDao.updateBySn(mOrder);
    }

    @Override
    public String selectProductSnByOrderSn(String zfbOrderSn) {
        return mOrderDao.selectProductSnByOrderSn(zfbOrderSn);
    }

    @Override
    public List<MOrder> selectNoSendProduct(Integer creatorSn, String orderStatus) {
        return mOrderDao.selectNoSendProduct(creatorSn,orderStatus);
    }
}